import * as THREE from 'three'
import { stats } from '../stats'
import { gui } from '../gui'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'

function createCourse22 (dom: HTMLElement) {
  const scene = new THREE.Scene()

  const camera = new THREE.PerspectiveCamera(75, dom.offsetWidth / dom.offsetHeight, 0.1, 1000)
  camera.position.set(30, 30, 30)

  const render = new THREE.WebGLRenderer()
  render.setClearColor(new THREE.Color(0xEEEEEE))
  render.setSize(dom.offsetWidth, dom.offsetHeight)
  render.shadowMap.enabled = true

  dom.appendChild(render.domElement)

  const axes = new THREE.AxesHelper(100)
  scene.add(axes)

  const controls = new OrbitControls(camera, render.domElement)
  controls.update()

  const groundGeom = new THREE.PlaneGeometry(200, 200, 4, 4)
  const groundMaterial = new THREE.MeshBasicMaterial({ color: 0x777777 })
  const groundMesh = new THREE.Mesh(groundGeom, groundMaterial)
  groundMesh.rotation.x = -Math.PI / 2
  groundMesh.position.x = -20
  scene.add(groundMesh)

  const cubeGeom = new THREE.BoxGeometry(15, 15, 15)
  const cubeMaterial = new THREE.MeshBasicMaterial({ color: 0x7777ff })
  const cubeMesh = new THREE.Mesh(cubeGeom, cubeMaterial)
  cubeMesh.position.set(0, 10, 0)
  scene.add(cubeMesh)

  const ctrlObj = {
    visible: true,
    transparent: false,
    opacity: 1,
    side: 'front',
    depthTest: true,
    depthWrite: true,
    alphaTest: 1,
    color: 0x7777ff,
    wireframe: false,
    map: true,
    reflectivity: 1,
    refractionRatio: 0.98,
    combine: 'Multiply',
    alphaMap: true
  }

  const control = gui
  const folder = control.addFolder('基础属性')
  folder.add(ctrlObj, 'visible').onChange(function (e: boolean) {
    cubeMaterial.visible = e
  })

  folder.add(ctrlObj, 'transparent').onChange(function (e: boolean) {
    cubeMaterial.transparent = e
  })

  folder.add(ctrlObj, 'opacity', 0, 1).onChange(function (e: number) {
    cubeMaterial.opacity = e
  })

  folder.add(ctrlObj, 'depthTest').onChange(function (e: boolean) {
    cubeMaterial.depthTest = e
  })

  folder.add(ctrlObj, 'depthWrite').onChange(function (e: boolean) {
    cubeMaterial.depthWrite = e
  })

  folder.add(ctrlObj, 'alphaTest', 0, 1).onChange(function (e: number) {
    cubeMaterial.alphaTest = e
  })

  folder.add(ctrlObj, 'side', ['front', 'back', 'double']).onChange(function (e: string) {
    switch (e) {
      case 'front':
        cubeMaterial.side = THREE.FrontSide
        break
      case 'back':
        cubeMaterial.side = THREE.BackSide
        break
      case 'double':
        cubeMaterial.side = THREE.DoubleSide
        break

      default:
        break
    }

    cubeMaterial.needsUpdate = true
  })

  const textureLoader = new THREE.TextureLoader()
  const bricks = textureLoader.load('https://dongli-three.oss-cn-shanghai.aliyuncs.com/brick_roughness.jpg')
  cubeMaterial.map = bricks

  const textureCube = createEnv()
  cubeMaterial.envMap = textureCube

  const Basicfolder = control.addFolder('MeshBasicMaterial')
  Basicfolder.addColor(ctrlObj, 'color').onChange(function (e: number) {
    cubeMaterial.color = new THREE.Color(e)
  })

  Basicfolder.add(ctrlObj, 'wireframe').onChange(function (e: boolean) {
    cubeMaterial.wireframe = e
  })

  Basicfolder.add(ctrlObj, 'map').onChange(function (e: boolean) {
    cubeMaterial.map = e ? bricks : null
    cubeMaterial.needsUpdate = true
  })

  Basicfolder.add(ctrlObj, 'reflectivity', 0, 1).onChange(function (e: number) {
    cubeMaterial.reflectivity = e
  })

  Basicfolder.add(ctrlObj, 'refractionRatio', 0, 1).onChange(function (e: number) {
    cubeMaterial.refractionRatio = e
  })

  Basicfolder.add(ctrlObj, 'combine', ['Multiply', 'Mix', 'Add']).onChange(function (e: string) {
    switch (e) {
      case 'Multiply':
        cubeMaterial.combine = THREE.MultiplyOperation
        break
      case 'Mix':
        cubeMaterial.combine = THREE.MixOperation
        break
      case 'Add':
        cubeMaterial.combine = THREE.AddOperation
        break

      default:
        break
    }

    cubeMaterial.needsUpdate = true
  })

  const alphaMapTx = textureLoader.load('https://dongli-three.oss-cn-shanghai.aliyuncs.com/alphaMap.jpg')
  cubeMaterial.alphaMap = alphaMapTx

  Basicfolder.add(ctrlObj, 'alphaMap').onChange(function (e: boolean) {
    cubeMaterial.alphaMap = e ? alphaMapTx : null
    cubeMaterial.needsUpdate = true
  })

  function createEnv () {
    const urls = [
      'https://dongli-three.oss-cn-shanghai.aliyuncs.com/posx.jpg',
      'https://dongli-three.oss-cn-shanghai.aliyuncs.com/negx.jpg',
      'https://dongli-three.oss-cn-shanghai.aliyuncs.com/posy.jpg',
      'https://dongli-three.oss-cn-shanghai.aliyuncs.com/negy.jpg',
      'https://dongli-three.oss-cn-shanghai.aliyuncs.com/posz.jpg',
      'https://dongli-three.oss-cn-shanghai.aliyuncs.com/negz.jpg'
    ]

    const cubeTxLoader = new THREE.CubeTextureLoader()
    const refCube = cubeTxLoader.load(urls)
    refCube.mapping = THREE.CubeRefractionMapping
    // refCube.format = THREE.RGBFormat
    return refCube
  }

  render.setAnimationLoop(anmation)

  function anmation () {
    stats.update()
    render.render(scene, camera)
  }

  return { camera, scene, render }
}

export {
  createCourse22
}
